package com.xbongbong.pro.statistics.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.domain.entity.ext.CkPaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.AggTypeEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.bi.XbbTableRefEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.bi.commons.constant.Constant;
import com.xbongbong.pro.bi.commons.pojo.AggFieldPojo;
import com.xbongbong.pro.bi.commons.pojo.vo.GroupSqlVO;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.statistic.enums.AdvancedComputingFirstEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.pojo.ChartFieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.pro.statistics.service.CkPaasFormDataService;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractPerformanceEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 聚合信息帮助类
 * @ClassName AggregationlHelper
 * @Author 梁鲁江
 * 创建时间 2021/6/28 13:45
 * 修改时间  2021/6/28 13:45
 **/
@Component
public class AggregationlHelper {
    public Logger logger = LoggerFactory.getLogger(getClass());
    @Resource
    private ComputedHelp computedHelp;
    @Resource
    private InitSqlHelper initSqlHelper;
    @Resource
    private CkPaasFormDataService ckPaasFormDataService;
    @Resource
    private CommonHelper commonHelper;
    @Resource
    private DescribeTableHelper describeTableHelper;
    /**
     * 图的解析
     * @param chartEntity
     * @param formIdTableMap
     * @param sortMap
     * @return
     * @throws XbbException
     */
    public Pair<GroupSqlVO, HashMap<String, Set<String>>> chartAggregationsBuilder(ChartEntity chartEntity, Map<Long, String> formIdTableMap, Map<String, String> sortMap) throws XbbException {
        //
        GroupSqlVO groupSqlVO = new GroupSqlVO();
        //分组字段放在colums
        List<String> groupColumnsList = new ArrayList<>();
        //分组字段放在group by 
        List<String> groupFieldsList = new ArrayList<>();
        Map<String, AggFieldPojo>  aggFieldMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> aggFieldsList = new ArrayList<>();
        List<String> sumTotalFieldsList = new ArrayList<>();
        List<String> subQuerySqlOfCountList = new ArrayList<>();
        List<String> summaryColumnAlisa = new ArrayList<>();
        Boolean isSingle = EsUtil.getSingle(chartEntity);
        FieldAttrPojo classifyAttr = JSONArray.parseArray(chartEntity.getChartClassify().toJSONString(), FieldAttrPojo.class).get(0);
        FieldAttrPojo valueAttr = JSONArray.parseArray(chartEntity.getChartValue().toJSONString(), FieldAttrPojo.class).get(0);
        List<FieldAttrPojo> valueAttrList = JSONArray.parseArray(chartEntity.getChartValue().toJSONString(), FieldAttrPojo.class);
        List<FieldAttrPojo> valueAttrSecondList = null;
        if (CollectionUtils.isNotEmpty(chartEntity.getChartValueSecond())){
            valueAttrSecondList = JSONArray.parseArray(chartEntity.getChartValueSecond().toJSONString(), FieldAttrPojo.class);
        }
        HashMap<String, Set<String>> selectItemsMap = Maps.newHashMap();
        //保存分组字段为下拉单选时的字段sql
        Map<String,FieldAttrPojo> comboFieldMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //分类设置字段
        initSqlHelper.addFieldaliasList(selectItemsMap,isSingle, groupColumnsList,groupFieldsList, formIdTableMap,  classifyAttr, classifyAttr.getAttr(), classifyAttr.getFormId(),sortMap, chartEntity,comboFieldMap,new ArrayList<>(),new ArrayList<>());
        AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(valueAttr.getAggType());
        Map<FieldAttrPojo,AggTypeEnum> fieldAttrEntityAggTypeEnumMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<FieldAttrPojo,AggTypeEnum> fieldAttrEntityAggTypeEnumSecondMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        if (Objects.nonNull(valueAttr)){
//            fieldAttrEntityAggTypeEnumMap.put(valueAttr,aggTypeEnum);
//        }
//        if (Objects.nonNull(valueAttrSecond)){
//            fieldAttrEntityAggTypeEnumMap.put(valueAttrSecond,aggTypeEnumSecond);
//        }
        if (CollectionUtils.isNotEmpty(valueAttrList)){
            for (FieldAttrPojo item : valueAttrList) {
                AggTypeEnum aggTypeEnum1 = AggTypeEnum.getByAlias(item.getAggType());
                if(Objects.equals(item.getAttr(),PaasConstant.COUNT)){
                    aggTypeEnum1 = AggTypeEnum.COUNT;
                    //单个值的时候 valueAttrList只有一个
                    aggTypeEnum =  AggTypeEnum.COUNT;
                }
                fieldAttrEntityAggTypeEnumMap.put(item, aggTypeEnum1);
            }
        }
        if (CollectionUtils.isNotEmpty(valueAttrSecondList)){
            for (FieldAttrPojo item : valueAttrSecondList) {
                AggTypeEnum aggTypeEnum1 = AggTypeEnum.getByAlias(item.getAggType());
                if(Objects.equals(item.getAttr(),PaasConstant.COUNT)){
                    aggTypeEnum1 = AggTypeEnum.COUNT;
                    //单个值的时候 valueAttrList只有一个
                    aggTypeEnum =  AggTypeEnum.COUNT;
                }
                fieldAttrEntityAggTypeEnumSecondMap.put(item,aggTypeEnum1);
            }
        }
        //系列为空则为二级聚合 不为空则为三级聚合
        if (!chartEntity.getChartSeries().isEmpty()) {
            FieldAttrPojo seriesAttr = JSONArray.parseArray(chartEntity.getChartSeries().toJSONString(), FieldAttrPojo.class).get(0);
            //系列设置字段
            initSqlHelper.addFieldaliasList(selectItemsMap,isSingle, groupColumnsList,groupFieldsList, formIdTableMap,  seriesAttr, seriesAttr.getAttr(), seriesAttr.getFormId(),sortMap, chartEntity,comboFieldMap,new ArrayList<>(),new ArrayList<>());
            for (FieldAttrPojo fieldAttrPojo : valueAttrList) {
                String attr = fieldAttrPojo.getAttr();
                //判断是否是计算字段作为值
                if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(),fieldAttrPojo.getFieldType())) {
                    computedHelp.addComputedField (chartEntity,fieldAttrPojo,fieldAttrEntityAggTypeEnumSecondMap.get(fieldAttrPojo),PaasConstant.LEFT,selectItemsMap,formIdTableMap,aggFieldMap,aggFieldsList,sortMap,sumTotalFieldsList,subQuerySqlOfCountList,summaryColumnAlisa);
                }else{
                    Long formId = fieldAttrPojo.getFormId();
                    addValuesField(PaasConstant.LEFT,formIdTableMap, aggFieldMap, aggFieldsList, isSingle, fieldAttrPojo, fieldAttrEntityAggTypeEnumMap.get(fieldAttrPojo), formId, attr,sortMap, sumTotalFieldsList,summaryColumnAlisa);
                    handleWorkOrderV2StayTimeStr(formId, formIdTableMap, selectItemsMap);
                }
            }
        } else {
            // 排序
            FieldAttrPojo sortAttr = null;
            int sortIndex = 0;
            int resultSortIndex = 0;
            String side = PaasConstant.LEFT;
            String sortMapKey = null;
            // 左侧是0,右侧是1
            int sideFlag = PaasConstant.LEFT_SIDE_FLAG;
            if (CollectionUtils.isNotEmpty(valueAttrList) && Objects.nonNull(sortMap)){
                for (FieldAttrPojo item : valueAttrList) {
                    for (Map.Entry<String, String> entry : sortMap.entrySet()) {
                        String k = entry.getKey();
                        if (Objects.equals(chartEntity.getChartType(), ChartTypeEnum.BIAXIAL_CHART.getCode())){
                            if (Objects.equals(item.getAttr() + "&" + item.getFieldType() + "&" + sideFlag, k)) {
                                sortAttr = item;
                                sortMapKey = k;
                                resultSortIndex = sortIndex;
                                break;
                            }
                        }else if (Objects.equals(item.getAttr(),PaasConstant.COUNT) && Objects.equals(item.getAttr() + "&" + item.getFieldType() + "&" + item.getFormId(), k)) {
                            sortAttr = item;
                            sortMapKey = k;
                            resultSortIndex = sortIndex;
                            break;
                        }else if (Objects.equals(item.getAttr() + "&" + item.getFieldType(), k)) {
                            sortAttr = item;
                            sortMapKey = k;
                            resultSortIndex = sortIndex;
                            break;
                        }
                    }
                    if (Objects.nonNull(sortAttr)){
                        break;
                    }
                    sortIndex ++ ;
                }
            }
            if (CollectionUtils.isNotEmpty(valueAttrSecondList) && Objects.nonNull(sortMap) && Objects.isNull(sortAttr)){
                sideFlag = PaasConstant.RIGHT_SIDE_FLAG;
                for (FieldAttrPojo item : valueAttrSecondList) {
                    for (Map.Entry<String, String> entry : sortMap.entrySet()) {
                        String k = entry.getKey();
                        if (Objects.equals(chartEntity.getChartType(),ChartTypeEnum.BIAXIAL_CHART.getCode())){
                            if (Objects.equals(item.getAttr() + "&" + item.getFieldType() + "&" + sideFlag, k)) {
                                sortAttr = item;
                                sortMapKey = k;
                                side = PaasConstant.RIGHT;
                                resultSortIndex = sortIndex;
                                break;
                            }
                        }else if (Objects.equals(item.getAttr(),PaasConstant.COUNT) && Objects.equals(item.getAttr() + "&" + item.getFieldType() + "&" + item.getFormId(), k)) {
                            sortAttr = item;
                            sortMapKey = k;
                            side = PaasConstant.RIGHT;
                            resultSortIndex = sortIndex;
                            break;
                        }else if (Objects.equals(item.getAttr() + "&" + item.getFieldType() , k)) {
                            sortAttr = item;
                            sortMapKey = k;
                            side = PaasConstant.RIGHT;
                            resultSortIndex = sortIndex;
                            break;
                        }
                    }
                    if (Objects.nonNull(sortAttr)){
                        break;
                    }
                    sortIndex ++ ;
                }
            }
            sortAttr = ( null != sortAttr ) ? sortAttr : valueAttr;
            addAggregations(selectItemsMap,PaasConstant.LEFT,fieldAttrEntityAggTypeEnumMap,isSingle,formIdTableMap, aggFieldMap, aggFieldsList,sortMap, sumTotalFieldsList,chartEntity,subQuerySqlOfCountList,summaryColumnAlisa);
            addAggregations(selectItemsMap,PaasConstant.RIGHT,fieldAttrEntityAggTypeEnumSecondMap,isSingle,formIdTableMap, aggFieldMap, aggFieldsList,sortMap, sumTotalFieldsList,chartEntity,subQuerySqlOfCountList,summaryColumnAlisa);
        }
//        sourceBuilder.aggregation(aggResult);
        groupSqlVO.setAggFieldMap(aggFieldMap);
        groupSqlVO.setAggFieldsList(aggFieldsList);
        groupSqlVO.setSumTotalFieldsList(sumTotalFieldsList);
        groupSqlVO.setGroupColumnsList(groupColumnsList);
        groupSqlVO.setGroupFieldsList(groupFieldsList);
        groupSqlVO.setComboFieldMap(comboFieldMap);
        groupSqlVO.setSubQuerySqlOfCountList(subQuerySqlOfCountList);
        groupSqlVO.setSummaryColumnAlisa(summaryColumnAlisa);
        Pair<GroupSqlVO, HashMap<String, Set<String>>> listHashMapPair = new ImmutablePair(groupSqlVO, selectItemsMap);
        return listHashMapPair;
    }
    /**
     * 双轴图左侧右侧可能会添加相同的字段，要区分，添加aggregation
     * @param side
     * @param fieldAttrEntityAggTypeEnumMap
     * @param isSingle
     * @param sumTotalFieldsList
     */
    void addAggregations(HashMap<String, Set<String>> selectItemMap, String side, Map<FieldAttrPojo, AggTypeEnum> fieldAttrEntityAggTypeEnumMap, Boolean isSingle, Map<Long, String> formIdTableMap, Map<String, AggFieldPojo> aggFieldMap, List<String> aggFieldsList, Map<String, String> sortMap, List<String> sumTotalFieldsList, ChartEntity chartEntity, List<String> subQuerySqlOfCountList,List<String> summaryColumnAlisa) throws XbbException {
        for (Map.Entry<FieldAttrPojo, AggTypeEnum> entry : fieldAttrEntityAggTypeEnumMap.entrySet()) {
            FieldAttrPojo fieldAttrPojo = entry.getKey();
            AggTypeEnum aggType = entry.getValue();
            String attr = fieldAttrPojo.getAttr();
            if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(), fieldAttrPojo.getFieldType())) {
                computedHelp.addComputedField(chartEntity,fieldAttrPojo,aggType,side,selectItemMap,formIdTableMap,aggFieldMap,aggFieldsList,sortMap,sumTotalFieldsList,subQuerySqlOfCountList,summaryColumnAlisa);
            } else {
                Long formId = fieldAttrPojo.getFormId();
                addValuesField( side,formIdTableMap, aggFieldMap, aggFieldsList, isSingle, fieldAttrPojo, aggType, formId, attr,sortMap, sumTotalFieldsList,summaryColumnAlisa);
                handleWorkOrderV2StayTimeStr(formId, formIdTableMap, selectItemMap);
            }
        }
    }

    /**
     * 统计表，汇总字段为停留时长时，selectItemMap没有stayTime
     * @param formId
     * @param formIdTableMap
     * @param selectItemMap
     */
    private void handleWorkOrderV2StayTimeStr(Long formId, Map<Long, String> formIdTableMap, HashMap<String, Set<String>> selectItemMap) {
        if (!Objects.equals(formId, Constant.nodeLogInfoFormId)
                || MapUtils.isEmpty(formIdTableMap) || MapUtils.isEmpty(selectItemMap)) {
            return;
        }
        Set<String> strings = Objects.isNull(selectItemMap.get(XbbTableRefEnum.WORK_ORDER_V2_NODE_LOG_INFO.getTableName()))
                ? new LinkedHashSet<>() : selectItemMap.get(XbbTableRefEnum.WORK_ORDER_V2_NODE_LOG_INFO.getTableName());
        String selectStayTimeStr = InitSqlHelper.getInstance().generatargMax(StringUtil.getDataBaseString("stayTime"));
        if (!strings.contains(selectStayTimeStr)) {
            InitSqlHelper.getInstance().addSelectCol(formIdTableMap, selectItemMap, Constant.nodeLogInfoFormId, selectStayTimeStr);
        }
    }

    /**
     * 统计表的处理
     * @param side
     * @param formIdTableMap
     * @param aggFieldMap
     * @param aggFieldsList
     * @param isSingle
     * @param valueAttr
     * @param aggTypeEnum
     * @param formId
     * @param attr
     * @param sortMap
     * @param sumTotalFieldsList
     */
    public void addValuesField(String side, Map<Long, String> formIdTableMap, Map<String, AggFieldPojo> aggFieldMap, List<String> aggFieldsList, Boolean isSingle, FieldAttrPojo valueAttr, AggTypeEnum aggTypeEnum, Long formId, String attr, Map<String, String> sortMap, List<String> sumTotalFieldsList,List<String> summaryColumnAlisa) {
            if (EsUtil.setInData(valueAttr.getFieldType())&& !EsUtil.specialOutData(valueAttr.getBusinessType(), valueAttr.getFieldType())) {
            String jsonExtract = XbbConstant.JSON_EXTRACT_DOUBLE;
            String aggExtractStr = null;
            //count 设置的时候可能设置为了sum
            if(Objects.equals(AggTypeEnum.COUNT.getCode(),aggTypeEnum.getCode()) || Objects.equals(AggTypeEnum.COUNT.getAlias(),attr)){
                aggExtractStr = AggTypeEnum.COUNT.getAlias() + "()";
                aggTypeEnum = AggTypeEnum.COUNT;
            }else {
                String tableAlias = formIdTableMap.get(formId);
                String originalAttr = attr;
                if (!isSingle) {
                    originalAttr = valueAttr.getOriginalAttr();
                }
                if (StringUtils.equals(XbbTableRefEnum.CONTRACT_PERFORMANCE.getTableName(),tableAlias)){
                    if (StringUtils.isNotEmpty(tableAlias) && StringUtils.isNotEmpty(originalAttr)) {
                        aggExtractStr = aggTypeEnum.getAlias() + "(" + tableAlias + "." + StringUtil.getDataBaseString(ContractPerformanceEnum.getRealAttr(originalAttr)) + ") ";
                    }
                }else {
                    aggExtractStr = aggTypeEnum.getAlias() + "(" + jsonExtract + "(" + tableAlias + ".`data`,'" + originalAttr + "')) ";
                }
            }
            //注意序号
            String key;
            Set<String> keySet = aggFieldMap.keySet();
            int i = 1;
            //统计值在一起的顺序
            int index = 0;
            if(keySet.isEmpty()){
                key = aggTypeEnum.getAlias() + "_" +i;
            }else {
                for (String s1 : keySet) {
                    String[] keyArray = s1.split("_");
                    String strType = keyArray[0];
                    String strI = keyArray[1];
                    if(Objects.equals(strType, aggTypeEnum.getAlias())){
                        int j = Integer.parseInt(strI) + 1;
                        if(i<j){
                            i = j;
                        }
                    }
                    index++;
                }
                key = aggTypeEnum.getAlias() + "_" +i;
            }
            aggFieldsList.add(aggExtractStr + " AS " + key);
            // 由于同环比不计算总计（总计不分页，不好算）
            JSONArray advancedComputing = valueAttr.getAdvancedComputing();
            if (AdvancedComputingFirstEnum.noneYearChain(advancedComputing)) {
                sumTotalFieldsList.add(aggExtractStr + " AS " + key);
            }
            summaryColumnAlisa.add(key);
            AggFieldPojo aggFieldPojo = new AggFieldPojo();
            aggFieldPojo.setAggTypeEnum(aggTypeEnum);
            aggFieldPojo.setAttr(attr);
            //多表关联，设置两个不同表的字段时，需要根据表单id进行区分
            aggFieldPojo.setFormId(valueAttr.getFormId());
            aggFieldPojo.setIndex(index);
            aggFieldPojo.setAxis(side);
            //
            aggFieldPojo.setLabelName(valueAttr.getLabelName());
            aggFieldPojo.setFieldType(valueAttr.getFieldType());
            aggFieldPojo.setAdvancedComputing(advancedComputing);
            aggFieldMap.put(key,aggFieldPojo);
            //
            String sortAttrValue = sortMap.get(attr);
            if(StringUtil.isNotEmpty(sortAttrValue) && (Objects.equals(sortAttrValue.trim(), "asc") || Objects.equals(sortAttrValue.trim(), "desc"))){
                String aggStr = aggExtractStr + " AS " + key + " " + sortAttrValue;
                sortMap.put(attr, aggStr);
            }
        }else {
            handleWorkOrderV2StayTime(side, aggFieldMap, aggFieldsList, valueAttr, aggTypeEnum, attr, sumTotalFieldsList);
            //TODO
        }
    }

    /**
     * 汇总字段时触发，处理停留时长
     * @param side
     * @param aggFieldMap
     * @param aggFieldsList
     * @param valueAttr
     * @param aggTypeEnum
     * @param attr
     * @param sumTotalFieldsList
     */
    private void handleWorkOrderV2StayTime(String side, Map<String, AggFieldPojo> aggFieldMap, List<String> aggFieldsList, FieldAttrPojo valueAttr, AggTypeEnum aggTypeEnum, String attr, List<String> sumTotalFieldsList) {
        //nodeLogInfo仅有stayTime 可作为汇总字段
        if (Objects.equals(valueAttr.getBusinessType(), XbbRefTypeEnum.WORK_ORDER_V2_NODE_LOG_INFO.getCode())
                && Objects.equals(valueAttr.getSaasAttr(), "stayTime")) {
            //注意序号
            String key;
            Set<String> keySet = aggFieldMap.keySet();
            int i = 1;
            //统计值在一起的顺序
            int index = 0;
            if (keySet.isEmpty()) {
                key = aggTypeEnum.getAlias() + "_" + i;
            } else {
                for (String s1 : keySet) {
                    String[] keyArray = s1.split("_");
                    String strType = keyArray[0];
                    String strI = keyArray[1];
                    if (Objects.equals(strType, aggTypeEnum.getAlias())) {
                        int j = Integer.parseInt(strI) + 1;
                        if (i < j) {
                            i = j;
                        }
                    }
                    index++;
                }
                key = aggTypeEnum.getAlias() + "_" + i;
            }
            String aggExtractStr;
            if (Objects.equals(AggTypeEnum.COUNT.getCode(), aggTypeEnum.getCode()) || Objects.equals(AggTypeEnum.COUNT.getAlias(), attr)) {
                aggExtractStr = AggTypeEnum.COUNT.getAlias() + "() AS " + key;
                aggTypeEnum = AggTypeEnum.COUNT;
            } else {
                aggExtractStr = aggTypeEnum.getAlias() + "(tb_work_order_v2_node_log_info.stay_time) AS " + key;
            }
            aggFieldsList.add(aggExtractStr);
            AggFieldPojo aggFieldPojo = new AggFieldPojo();
            aggFieldPojo.setAggTypeEnum(aggTypeEnum);
            aggFieldPojo.setAttr(attr);
            //多表关联，设置两个不同表的字段时，需要根据表单id进行区分
            aggFieldPojo.setFormId(valueAttr.getFormId());
            aggFieldPojo.setIndex(index);
            aggFieldPojo.setAxis(side);
            //
            aggFieldPojo.setLabelName(valueAttr.getLabelName());
            aggFieldPojo.setFieldType(valueAttr.getFieldType());
            aggFieldMap.put(key, aggFieldPojo);
            sumTotalFieldsList.add(aggExtractStr);
        }
    }

    /**
     * 指标图
     * @param chartEntity
     * @param sortMap
     * @throws XbbException
     * @return
     */
    public Pair<GroupSqlVO, HashMap<String, Set<String>>> targetChartAggregation(ChartEntity chartEntity, Map<Long, String> formIdTableMap, Map<String, String> sortMap) throws XbbException {
        GroupSqlVO groupSqlVO = new GroupSqlVO();
        List<String> groupColumnsList = new ArrayList<>();
        List<String> groupFieldsList = new ArrayList<>();
        Map<String, AggFieldPojo>  aggFieldMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> aggFieldsList = new ArrayList<>();
        List<String> sumTotalFieldsList = new ArrayList<>();
        List<String> subQuerySqlOfCountList = new ArrayList<>();
        List<String> summaryColumnAlisa = new ArrayList<>();
        Boolean isSingle = EsUtil.getSingle(chartEntity);
        List<FieldAttrPojo> groupAttrList = JSONArray.parseArray(chartEntity.getRowGroupAttr().toJSONString(), FieldAttrPojo.class);
        List<FieldAttrPojo> summaryAttrList = JSONArray.parseArray(chartEntity.getSummaryAttr().toJSONString(), FieldAttrPojo.class);
        HashMap<String, Set<String>> selectItemsMap = Maps.newHashMap();
        Map<String,FieldAttrPojo> comboFieldMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionsUtil.isNotEmpty(groupAttrList)) {
            for (int i = 0; i < groupAttrList.size(); i++) {
                StringBuilder field = new StringBuilder();
                FieldAttrPojo fieldAttrPojo = groupAttrList.get(i);
                /*Boolean asc = null;
                if (sortMap != null) {
                    String ascStr = sortMap.get(aggName1.toString());
                    asc = ascStr == null ? null : Objects.equals(ascStr, StringConstant.SORT_ASC_TAG);
                }*/
                if (i == 0) {
                    initSqlHelper.addFieldaliasList(selectItemsMap,isSingle, groupColumnsList,groupFieldsList, formIdTableMap,  fieldAttrPojo, fieldAttrPojo.getAttr(), fieldAttrPojo.getFormId(),sortMap, chartEntity,comboFieldMap,new ArrayList<>(),new ArrayList<>());
                }
            }
            if (CollectionsUtil.isNotEmpty(summaryAttrList)) {
                for (FieldAttrPojo fieldAttrPojo : summaryAttrList) {
                    Long formId = fieldAttrPojo.getFormId();
                    String attr = fieldAttrPojo.getAttr();
                    String aggType = fieldAttrPojo.getAggType();
                    AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(aggType);
                    //如果是计算字段
                    if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(),fieldAttrPojo.getFieldType())) {
                        computedHelp.addComputedField(chartEntity,fieldAttrPojo,aggTypeEnum,PaasConstant.LEFT,selectItemsMap,formIdTableMap,aggFieldMap,aggFieldsList,sortMap,sumTotalFieldsList,subQuerySqlOfCountList,summaryColumnAlisa);
                    }else{
                        addValuesField(PaasConstant.LEFT,formIdTableMap, aggFieldMap, aggFieldsList, isSingle, fieldAttrPojo, aggTypeEnum, formId, attr,sortMap, sumTotalFieldsList,summaryColumnAlisa);
                        handleWorkOrderV2StayTimeStr(formId, formIdTableMap, selectItemsMap);
                    }
                }
            }
           /* sourceBuilder.aggregation(tempAggregationBuilder);
            //累加所有桶的值
            SumBucketPipelineAggregationBuilder sumBucket = new SumBucketPipelineAggregationBuilder("sum", aggName1.append('>').append(aggName2).toString());
            sourceBuilder.aggregation(sumBucket);*/
        }else{
            //无分组字段
            //指标有可能是数字，有可能是计数
            if (CollectionsUtil.isNotEmpty(summaryAttrList)) {
                for (FieldAttrPojo fieldAttrPojo : summaryAttrList) {
                    Long formId = fieldAttrPojo.getFormId();
                    String attr = fieldAttrPojo.getAttr();
                    String aggType = fieldAttrPojo.getAggType();
                    AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(aggType);
                    //如果是计算字段，需要判断是否是计算字段
                    if (Objects.equals(FieldTypeEnum.COMPUTED_FIELD.getType(),fieldAttrPojo.getFieldType())) {
                        computedHelp.addComputedField(chartEntity,fieldAttrPojo,aggTypeEnum,PaasConstant.LEFT,selectItemsMap,formIdTableMap,aggFieldMap,aggFieldsList,sortMap,sumTotalFieldsList,subQuerySqlOfCountList,summaryColumnAlisa);
                    }else{
                        addValuesField(PaasConstant.LEFT,formIdTableMap, aggFieldMap, aggFieldsList, isSingle, fieldAttrPojo, aggTypeEnum, formId, attr,sortMap, sumTotalFieldsList,summaryColumnAlisa);
                        handleWorkOrderV2StayTimeStr(formId, formIdTableMap, selectItemsMap);
                    }
                }
            }
        }
        groupSqlVO.setAggFieldMap(aggFieldMap);
        groupSqlVO.setAggFieldsList(aggFieldsList);
        groupSqlVO.setSumTotalFieldsList(sumTotalFieldsList);
        groupSqlVO.setGroupColumnsList(groupColumnsList);
        groupSqlVO.setGroupFieldsList(groupFieldsList);
        groupSqlVO.setComboFieldMap(comboFieldMap);
        groupSqlVO.setSubQuerySqlOfCountList(subQuerySqlOfCountList);
        groupSqlVO.setSummaryColumnAlisa(summaryColumnAlisa);
        Pair<GroupSqlVO, HashMap<String, Set<String>>> listHashMapPair = new ImmutablePair(groupSqlVO, selectItemsMap);
        return listHashMapPair;
    }


    /**
     * 统计表
     * @return
     */
    public Pair<GroupSqlVO, HashMap<String, Set<String>>> statisticTableAggregation(ChartEntity chartEntity, Map<Long, String> formIdTableMap, Map<String, String> sortMap) throws XbbException {
        GroupSqlVO groupSqlVO = new GroupSqlVO();
        //分组字段放在colums
        List<String> groupColumnsList = new ArrayList<>();
        List<String> rowGroupColumnsList = new ArrayList<>();
        List<String> colGroupColumnsList = new ArrayList<>();
        //分组字段放在group by 
        List<String> groupFieldsList = new ArrayList<>();
        List<String> rowGroupFieldsList = new ArrayList<>();
        List<String> colGroupFieldsList = new ArrayList<>();
        Map<String, AggFieldPojo>  aggFieldMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        JSONArray rowGroupAttr = chartEntity.getRowGroupAttr();
        JSONArray colGroupAttr = chartEntity.getColGroupAttr();
        Boolean isSingle = EsUtil.getSingle(chartEntity);
        HashMap<String, Set<String>> selectItemsMap = Maps.newHashMap();
        Map<String,FieldAttrPojo> comboFieldMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if(rowGroupAttr !=null && rowGroupAttr.size() > 0){
            List<FieldAttrPojo> rowGroupAttrList = JSONArray.parseArray(rowGroupAttr.toJSONString(), FieldAttrPojo.class);
            setGroupFields(selectItemsMap,formIdTableMap, sortMap, rowGroupColumnsList, rowGroupFieldsList, isSingle, rowGroupAttrList, chartEntity,comboFieldMap);
            groupColumnsList.addAll(rowGroupColumnsList);
            groupFieldsList.addAll(rowGroupFieldsList);
        }
        if(colGroupAttr !=null && colGroupAttr.size() > 0){
            List<FieldAttrPojo> colGroupAttrList = JSONArray.parseArray(colGroupAttr.toJSONString(), FieldAttrPojo.class);
            setGroupFields(selectItemsMap,formIdTableMap, sortMap, colGroupColumnsList, colGroupFieldsList, isSingle, colGroupAttrList, chartEntity,comboFieldMap);
            groupColumnsList.addAll(colGroupColumnsList);
            groupFieldsList.addAll(colGroupFieldsList);
        }
        JSONArray summaryAttr = chartEntity.getSummaryAttr();
        List<String> aggFieldsList = new ArrayList<>();
        List<String> sumTotalFieldsList = new ArrayList<>();
        //子查询外层SQL数组
        List<String> subQuerySqlOfCountList = new ArrayList<>();
        List<String> summaryColumnAlisa = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(summaryAttr)){
            Map<FieldAttrPojo,AggTypeEnum> fieldAttrEntityAggTypeEnumMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<FieldAttrPojo> summaryAttrList = JSONArray.parseArray(summaryAttr.toJSONString(), FieldAttrPojo.class);
            for (int i = 0; i < summaryAttrList.size(); i++) {
                FieldAttrPojo item = summaryAttrList.get(i);
                AggTypeEnum aggTypeEnum1 = AggTypeEnum.getByAlias(item.getAggType());
                if(Objects.equals(item.getAttr(),PaasConstant.COUNT)){
                    aggTypeEnum1 = AggTypeEnum.COUNT;
                }
                fieldAttrEntityAggTypeEnumMap.put(item, aggTypeEnum1);
                //TODO 定义了linkedHashMap应该不需要再要序号
//                item.setGroupIndex(i);
            }
            addAggregations(selectItemsMap,PaasConstant.LEFT,fieldAttrEntityAggTypeEnumMap,isSingle,formIdTableMap, aggFieldMap, aggFieldsList,sortMap, sumTotalFieldsList,chartEntity,subQuerySqlOfCountList,summaryColumnAlisa);
        }
        groupSqlVO.setAggFieldMap(aggFieldMap);
        groupSqlVO.setAggFieldsList(aggFieldsList);
        groupSqlVO.setSumTotalFieldsList(sumTotalFieldsList);
        groupSqlVO.setGroupColumnsList(groupColumnsList);
        groupSqlVO.setRowGroupColumnsList(rowGroupColumnsList);
        groupSqlVO.setColGroupColumnsList(colGroupColumnsList);
        groupSqlVO.setGroupFieldsList(groupFieldsList);
        groupSqlVO.setRowGroupFieldsList(rowGroupFieldsList);
        groupSqlVO.setColGroupFieldsList(colGroupFieldsList);
        groupSqlVO.setComboFieldMap(comboFieldMap);
        groupSqlVO.setSubQuerySqlOfCountList(subQuerySqlOfCountList);
        groupSqlVO.setSummaryColumnAlisa(summaryColumnAlisa);
        Pair<GroupSqlVO, HashMap<String, Set<String>>> listHashMapPair = new ImmutablePair(groupSqlVO, selectItemsMap);
        return listHashMapPair;
    }

    private void setGroupFields(HashMap<String, Set<String>> selectItemsMap,Map<Long, String> formIdTableMap, Map<String, String> sortMap, List<String> groupColumnsList, List<String> groupFieldsList, Boolean isSingle, List<FieldAttrPojo> rowGroupAttrList,ChartEntity chartEntity,Map<String,FieldAttrPojo> comboFieldMap) throws XbbException {
        if (CollectionsUtil.isNotEmpty(rowGroupAttrList)) {
            for (FieldAttrPojo fieldAttrPojo : rowGroupAttrList) {
                initSqlHelper.addFieldaliasList(selectItemsMap,isSingle, groupColumnsList, groupFieldsList, formIdTableMap,
                        fieldAttrPojo, fieldAttrPojo.getAttr(), fieldAttrPojo.getFormId(), sortMap, chartEntity,comboFieldMap,new ArrayList<>(),new ArrayList<>());
            }
        }
    }



    /**
     * 获取关联字段对应的数据
     * @param chartEntity
     * @param jsonArray
     * @return
     */
    public Map<String, Map<String, String>> getLinkMap(ChartEntity chartEntity, JSONArray jsonArray) {
        Map<String, Map<String, String>> attrLinkMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionUtils.isEmpty(jsonArray)) {
            return attrLinkMap;
        }
        boolean isSingle = EsUtil.getSingle(chartEntity);
        List<ChartFieldAttrPojo> linkAttrList = new ArrayList<>();
        describeTableHelper.getStringMapMap(chartEntity, attrLinkMap, linkAttrList);
        if (CollectionUtils.isEmpty(linkAttrList)) {
            return attrLinkMap;
        }
        Map<Long, String> formIdTableMap = commonHelper.getFormIdTableMap(chartEntity, isSingle);
        for (ChartFieldAttrPojo fieldAttrPojo : linkAttrList) {
            StringBuffer stringBuffer = new StringBuffer();
            stringBuffer.append(" select ");
            Long formId = fieldAttrPojo.getFormId();
            String attrJsonExtract = InitSqlHelper.getExtractFuntion(fieldAttrPojo.getFieldType(), null);
            StringBuffer innerBuffer = new StringBuffer();
            innerBuffer.append("(").append(attrJsonExtract).append("(").append("`data`,'");
            String attr = fieldAttrPojo.getAttr();
            if (!isSingle) {
                attr = fieldAttrPojo.getOriginalAttr();
            }
            if (StringUtils.equals(XbbConstant.JSON_EXTRACT,attrJsonExtract)){
                innerBuffer.append(attr).append("','").append(XbbConstant.STRING_CONSTANT);
            }else {
                innerBuffer.append(attr);
            }
            innerBuffer.append("'))  AS  ").append(attr);
            stringBuffer.append(XbbConstant.DISTINCT).append(" ON (").append(innerBuffer).append(" ) ");
            stringBuffer.append(innerBuffer);
            stringBuffer.append(",");
            String linkedText = fieldAttrPojo.getLinkedText();
            JSONObject linkedJsonObject = fieldAttrPojo.getLinkedAttr();
            if (EsUtil.setInData(linkedJsonObject.getInteger("fieldType"))) {
                String jsonExtract = XbbConstant.JSON_EXTRACT;
                if (Objects.equals(FieldTypeEnum.NUM.getType(), linkedJsonObject.getInteger("fieldType")) || Objects.equals(FieldTypeEnum.STAR.getType(), linkedJsonObject.getInteger("fieldType"))) {
                    jsonExtract = XbbConstant.JSON_EXTRACT_DOUBLE;
                } else if (Objects.equals(FieldTypeEnum.DATETIME.getType(), linkedJsonObject.getInteger("fieldType"))) {
                    jsonExtract = XbbConstant.JSON_EXTRACT_INT;
                }
                if (!isSingle) {
                    //多表LinkedText是被修改过的字段，LinkedAttr里面的attr是原始字段
                    linkedText = linkedJsonObject.getString("attr");
                }
                String extractString = CommonHelper.getExtractString(jsonExtract,null,linkedText);
                stringBuffer.append(extractString);
                stringBuffer.append(" AS ");
                stringBuffer.append(linkedText);
            }
            //每个关联字段要单独查
            Set<String> idSet = new HashSet<>();
            String key = attr;
            if (!isSingle) {
                key =  fieldAttrPojo.getAttr();
            }
            for (int dataI = 0; dataI < jsonArray.size(); dataI++) {
                JSONObject resultObj = jsonArray.getJSONObject(dataI);
                String value = resultObj.getString(key);
                if (value != null) {
                    idSet.add(value);
                }
            }
            if (CollectionUtils.isNotEmpty(idSet)) {
                stringBuffer.append(" from ");
                stringBuffer.append(" ( SELECT id,argMax(data,update_time) as data,argMax(del,update_time) as del,argMax(flow_status,update_time) as flow_status from ");
                stringBuffer.append(formIdTableMap.get(formId));
                stringBuffer.append(" prewhere ");
                stringBuffer.append(" corpid = '").append(chartEntity.getCorpid()).append("'")
                        .append(" AND  form_id = ").append(formId)
                        .append(" group by id having del = 0  AND  flow_status in [0, 2]  AND " );
                //stringBuffer.append(attrJsonExtract + "(" + "`data`,'" + attr + "')");
                stringBuffer.append(CommonHelper.getExtractString(attrJsonExtract,null,attr));
                stringBuffer.append(" in ");
                StringBuffer valueBuffer = new StringBuffer();
                valueBuffer.append("[");
                List<String> idList = new ArrayList<>(idSet);

                if (!Objects.equals(attrJsonExtract, XbbConstant.JSON_EXTRACT)) {
                    for (int i = 0; i < idList.size(); i++) {
                        if (i != 0) {
                            valueBuffer.append(",");
                        }
                        valueBuffer.append(idList.get(i));
                    }
                } else {
                    for (int i = 0; i < idList.size(); i++) {
                        if (i != 0) {
                            valueBuffer.append(",");
                        }
                        valueBuffer.append("'");
                        valueBuffer.append(idList.get(i));
                        valueBuffer.append("'");
                    }
                }
                valueBuffer.append("]");
                stringBuffer.append(valueBuffer);
                stringBuffer.append(" ) ");
                stringBuffer.append(" limit ");
                stringBuffer.append(idSet.size());
                List<CkPaasFormDataEntityExt> ckSingleResultList = ckPaasFormDataService.findEntitysBySql(stringBuffer.toString());
                if(commonHelper.getPrintLog(chartEntity.getCorpid())){
                    //图表id   
                    logger.info("CK===link===chartId==="+chartEntity.getId()+"===SQL==="+stringBuffer.toString());
                }
                JSONArray linkJsonArray = JSONArray.parseArray(JSON.toJSONString(ckSingleResultList));
                Map<String, String> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (int i = 0; i < linkJsonArray.size(); i++) {
                    JSONObject json = linkJsonArray.getJSONObject(i);
                    Object o = json.get(attr);
                    if (o != null) {
                        map.put(o.toString(), json.get(linkedText).toString());
                    }
                }
                attrLinkMap.put(attr, map);
            }
        }

        return attrLinkMap;
    }

}

